import * as PIXI from 'pixi.js';

// 默认导出单利卷轴构造函数
export default class Reel {
    // 单列卷轴列表容器
    public readonly container: PIXI.Container;
    public readonly textures: Array<PIXI.Texture>;
    // 单列卷轴元素列表对象
    public sprites: Array<PIXI.Sprite> = [];
    private readonly hornContainerHeight: number;
    private readonly hornContainerWidth: number;
    private readonly ticker: PIXI.Ticker;

    constructor(app: PIXI.Application, position: number, hornContainer: PIXI.Container) {
        // 拿到舞台高度
        this.hornContainerHeight = hornContainer.height
        this.hornContainerWidth = hornContainer.width
        // 拿到舞台的循环器
        this.ticker = app.ticker;

        // 创建一个单列元素列表容器对象
        this.container = new PIXI.Container();
        // 创建元素纹理列表对象
        this.textures = [
            <PIXI.Texture>app.loader.resources!['SYM1.png']!.texture,
            <PIXI.Texture>app.loader.resources!['SYM2.png']!.texture,
            <PIXI.Texture>app.loader.resources!['SYM3.png']!.texture,
            <PIXI.Texture>app.loader.resources!['SYM4.png']!.texture,
            <PIXI.Texture>app.loader.resources!['SYM5.png']!.texture,
            <PIXI.Texture>app.loader.resources!['SYM6.png']!.texture,
        ];
        // 调用生成方法
        this.generate(position);
    }

    // 生成方法
    private generate(position: number) {
        // 单列卷轴宽度
        const REEL_WIDTH = this.hornContainerWidth / 5 - 5;
        // 单列卷轴偏移量(距离单列卷轴中心的左侧偏移量)
        const REEL_OFFSET_BETWEEN = 5;
        // 单列卷轴元素显示元素个数
        const NUMBER_OF_ROWS = 3;
        // 设置单列容器横坐标位置(每个单列卷轴索引 * 单列卷轴宽度)
        this.container.x = position * REEL_WIDTH;
        // 循环遍历(单列卷轴元素显示元素个数 + 1 = 单列卷轴元素个数)
        for (let i = 0; i < NUMBER_OF_ROWS + 1; i++) {
            // 创建卷轴元素精灵(随机从元素纹理列表中选取一个)
            const symbol = new PIXI.Sprite(this.textures[Math.floor(Math.random() * this.textures.length)]);
            // 设置卷轴元素精灵的宽高
            symbol.width = this.hornContainerWidth / 7
            symbol.height = this.hornContainerWidth / 7
            // 设置卷轴元素精灵的缩放比例(会影响元素精灵的宽度)
            // symbol.scale.set(0.5);
            // 计算出宽度差(单列卷轴宽度 - 卷轴元素精灵宽度)
            const widthDiff = REEL_WIDTH - symbol.width;
            // 设置卷轴元素精灵的横坐标位置(每个单列卷轴索引 * 单列卷轴偏移量 + 宽度差 / 2 )
            symbol.x = position * REEL_OFFSET_BETWEEN + widthDiff / 2;
            // 单列元素之间底部间距((舞台高度 - 卷轴元素精灵高度 * 3) / 3)
            // 卷轴元素精灵高度 * 3 = 单列卷轴中元素的高度和
            // 舞台高度 - 单列卷轴中元素的高度和 = 单列卷轴中除元素外的空间高度
            // 单列卷轴中除元素外的空间高度 / 3 = 可分配给每个元素的底部间距
            const yOffset = (this.hornContainerHeight - symbol.height * 3) / 3;
            // 单元格高度(卷轴元素精灵高度 + 元素底部内间距)
            const cellHeight = symbol.height + yOffset;
            // 单元格顶部内间距( 元素底部内间距 / 2)
            const paddingTop = yOffset / 2;
            // 设置卷轴元素精灵的纵坐标位置( (当前卷轴元素索引 - 1) * 卷轴单元格高度 + 单元格内间距高度)
            symbol.y = (i - 1) * cellHeight + paddingTop;
            // 将卷轴元素添加到元素列表中
            this.sprites.push(symbol);
            // 将卷轴元素添加到单列元素列表容器中
            this.container.addChild(symbol);
        }
    }

    // 单列卷轴旋转一次的方法
    spinOneTime() {
        // 单列卷轴旋转时的速度
        // let speed = 30;
        let speed = 30;
        // 运行状态(默认停止)
        let doneRunning = false;
        // (舞台高度 - 卷轴元素高度 * 3) / 3 / 2
        // 舞台高度 - 卷轴元素高度 * 3  = 舞台除卷轴元素外剩余高度
        // 舞台除卷轴元素外剩余高度 / 3 = 每个卷轴元素均分的剩余高度
        // 每个卷轴元素均分的剩余高度 / 2 = 纵坐标偏移量
        let yOffset = (this.hornContainerHeight - this.sprites[0].height * 3) / 3 / 2;
        // 返回一个Promise的回调函数
        return new Promise<void>(resolve => {
            // 创建一个回调函数(在开启游戏循环时间内不停执行)
            const tick = () => {
                // 遍历单列卷轴元素
                for (let i = this.sprites.length - 1; i >= 0; i--) {
                    // 拿到当前卷轴元素
                    const symbol = this.sprites[i];
                    // 如果当前卷轴元素的纵坐标 + 移动速度 > 舞台高度 + 纵坐标偏移量 
                    if (symbol.y + speed > this.hornContainerHeight + yOffset) {
                        // 设置运行状态为运行
                        doneRunning = true;
                        // 屏幕高度 - 当前卷轴元素的纵坐标 + 纵坐标偏移量
                        speed = this.hornContainerHeight - symbol.y + yOffset;
                        // 更新当前卷轴元素的纵坐标(-(当前卷轴元素高度 + 纵坐标偏移量))
                        symbol.y = -(symbol.height + yOffset);
                    } else {
                        // 更新当前卷轴元素的纵坐标( 当前卷轴元素的纵坐标 + 移动速度)
                        symbol.y += speed;
                    }

                    // 如果卷轴元素移除卷轴容器则隐藏
                    if (symbol.y > this.hornContainerHeight - this.hornContainerHeight / 5 || symbol.y < 0) {
                        symbol.visible = false
                    } else {
                        symbol.visible = true
                    }

                    // 如果遍历到最后一个元素并且运行状态为运行中
                    if (i === 0 && doneRunning) {
                        // 移除单列卷轴中的最后一个元素
                        let t = this.sprites.pop();
                        // 如果这个元素存在,将这个被移除的元素添加到单列卷轴的最前面
                        if (t) this.sprites.unshift(t);
                        // 移除监听函数
                        // 删除与回调函数匹配的任何处理程序。如果删除后没有处理程序，则取消动画帧。
                        this.ticker.remove(tick);
                        resolve();
                    }
                }
            }
            // 开启游戏循环
            this.ticker.add(tick);
        });
    }
}
